本篇同步發文於個人網站: Encapsulation
This article references the chapter 7 ” Encapsulation ” of Refactoring: Improving the Design of Existing Code (2nd Edition). Author had highlighted many important refactorings in this chapter.
(adsbygoogle = window.adsbygoogle || []).push({});
I use .NET C# to practice with these refactorings and upload to Github.
(Photo from Pixabay: https://pixabay.com/illustrations/plumber-repair-tools-pipe-plunger-4427401/ )
Encapsulate Record
Tips
- For mutable data, use Class object instead of Record.
- If some record has nested data (list/hash/….), encapsulating this nested data is better.
- Usually use a class to encapsulate the record and create the access methods in the class.
- For nested data, we first focus on “Update Method”, then “Read Method” can return the copy / readonly proxy of the data.
- If a record’s field is also a complex structure, consider to use Encapsulate Record or Encapsulate Collection.
Examples:
- Simple Encapsulation
- Encapsulating a Nested Record
Github
Encapsulate Collection
Tips
- Usually add “Add” and “Remove” functions for accessing the collection
- Create a function that returns the copy of the collection. This avoids changing the original collection
- If we want set the collection, use the copy of parameter collection to set.
Examples:
Github
Replace Primitive with Object
Tips
- Some simple number/string instances will has complex logic, we should encapsulate them into classes. These classes are value classes.
- Consider Change Reference to Value or Change Value to Reference for the created object.
Examples:
Github
Replace Temp with Query
Tips
- This skill is used for the temp variable that is calculated once.
- Some temp variable is calculated many times, we also extract its calculation logic into query function.
Examples:
Github
Extract Class
Tips
- If one class’s responsibility is too huge, we consider that the class is split into main class and sub class. Sub class has the closed activities of functions/data.
Examples:
Github
(adsbygoogle = window.adsbygoogle || []).push({});
Inline Class
Tips
- If one class’s responsibility has no reason to exist by its single class, move this class’s member into another class.
Examples:
Github
Hide Delegate
Tips
- Create the delegate function to hide the inner relationship between the called object and the caller. If the called object changes, the caller still uses the delegate function without knowing the change.
Examples:
Github
Remove Middle Man
Tips
- If the delegate functions are too many, adjust caller to directly call the target object.
Examples:
- Just use the Hide Delegate example from end to start
Substitute Algorithm
Tips
- If the new algorithm is easy to maintain, we consider that the old algorithm is replaced by the new one.
Examples:
// before
static string FindPerson(string[] people)
{
for(int i = 0; i < people.Length; i++)
{
if (people[i] == "Don")
{
return "Don";
}
if (people[i] == "John")
{
return "John";
}
if (people[i] == "Kent")
{
return "Kent";
}
}
return "";
}
// after
static string FindPerson(string[] people)
{
string[] candidates = new string[]{"Don", "John", "Kent"};
return people.FirstOrDefault(x => candidates.Contains(x)) ?? "";
}
Conclusion
This chapter introduces me to the concept of complete encapsulation! If you want to learn detailed motivation and mechanics, study the chapter 7 ” Encapsulation ” of Refactoring: Improving the Design of Existing Code (2nd Edition). and it improves our programmer’s ability.